package com.fowo.api.common.query;

import lombok.extern.slf4j.Slf4j;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Slf4j
public class SqlInjectionUtil {

    private final static String XSS_STR = "extractvalue|updatexml|geohash|gtid_subset|gtid_subtract|exec |drop |count |chr |mid |master |truncate |char |declare |-- |< |/ |or |+|user()";

    /**
     * 正则 user() 匹配更严谨
     */
    private final static String REGULAR_EXPRE_USER = "user[\\s]*\\([\\s]*\\)";
    /**
     * 正则 show tables
     */
    private final static String SHOW_TABLES = "show\\s+tables";

    /**
     * sql注释的正则
     */
    private final static Pattern SQL_ANNOTATION = Pattern.compile("/\\*[\\s\\S]*\\*/");


    /**
     * sql注入过滤处理，遇到注入关键字抛异常
     *
     * @param value
     */
    public static void filterContent(String value) {
        filterContent(value, null);
    }

    /**
     * sql注入过滤处理，遇到注入关键字抛异常
     *
     * @param value
     * @return
     */
    public static void filterContent(String value, String customXssString) {
        if (value == null || "".equals(value)) {
            return;
        }
        // 校验sql注释 不允许有sql注释
        checkSqlAnnotation(value);
        // 统一转为小写
        value = value.toLowerCase();

        String[] xssArr = XSS_STR.split("\\|");
        for (int i = 0; i < xssArr.length; i++) {
            if (value.indexOf(xssArr[i]) > -1) {
                log.error("请注意，值可能存在SQL注入风险!---> {} 存在SQL注入关键词---> {}", value, xssArr[i]);
                throw new RuntimeException("请注意，值可能存在SQL注入风险!--->" + value);
            }
        }
        if (customXssString != null) {
            String[] xssArr2 = customXssString.split("\\|");
            for (int i = 0; i < xssArr2.length; i++) {
                if (value.indexOf(xssArr2[i]) > -1) {
                    log.error("请注意，值可能存在SQL注入风险!---> {} 存在SQL注入关键词---> {}", value, xssArr2[i]);
                    throw new RuntimeException("请注意，值可能存在SQL注入风险!--->" + value);
                }
            }
        }
        if (Pattern.matches(SHOW_TABLES, value) || Pattern.matches(REGULAR_EXPRE_USER, value)) {
            throw new RuntimeException("请注意，值可能存在SQL注入风险!--->" + value);
        }
        return;
    }

    /**
     * 校验是否有sql注释
     *
     * @return
     */
    public static void checkSqlAnnotation(String str) {
        Matcher matcher = SQL_ANNOTATION.matcher(str);
        if (matcher.find()) {
            String error = "请注意，值可能存在SQL注入风险---> \\*.*\\";
            log.error(error);
            throw new RuntimeException(error);
        }
    }
}
